#ifndef CFACTORY_H
#define CFACTORY_H

#if defined WINDOWS
// BUG: C4786 Warning Is Not Disabled with #pragma Warning
// STATUS: Microsoft has confirmed this to be a bug in the Microsoft product.
// This warning can be ignored. This occured only in the <map> container.
#pragma warning (disable : 4786 4787)
#endif

#include <map>
#include <string>

#define REGISTER(_c) (new class_buffer<_c>())
#define REGISTER_OBJECT(_c, pointer) (new class_buffer<_c>(pointer))


class class_buffer_base
{
  protected:
   void *pdata;

  public:
    virtual void *getObject() = 0;
   class_buffer_base() : pdata(NULL) {}
   class_buffer_base(void *pvoid) : pdata(pvoid) {}

    virtual ~class_buffer_base(){}
};


template <class type_object>
class class_buffer : public class_buffer_base
{
  public:
    virtual void *_getObject()
    {
      if(pdata == NULL)
      {
        return pdata = new type_object;
      }
      else
        return pdata;
    };

    virtual void *getObject()
    {
      return (type_object*)_getObject();
    }


  class_buffer() {}
  class_buffer(void *pvoid) : class_buffer_base(pvoid)  {}
  virtual ~class_buffer()
  {
    if(pdata != NULL)
    {
      delete (type_object*)pdata;
      pdata = NULL;
    }
  }

};


template <class Class>
class CFactory
{
public:
  CFactory() {};
  virtual ~CFactory()
  {
    while(!class_array.empty())
    {
      deRegitrateObject(class_array.begin()->first);
    }
  };

public:

  void Register(class_buffer_base *reg, const std::string& name)
   {
     class_array[name] = reg;
   };


  Class *getRegisterClass(const std::string& name)
  {
    if(class_array[name] != NULL)
     return (Class*)(class_array[name]->getObject());
    return 0;
  };

  void deRegitrateObject(const std::string& name)
  {
    if(class_array[name] != NULL)
    {
      delete class_array[name];
      class_array[name] = NULL;
      class_array.erase(name);
    }
  }

private:
  std::map<std::string, class_buffer_base*> class_array;
};

#endif // CFACTORY_H
